<?php

namespace core;

class Model
{
    const ALL = 2;
    const ROW = 1;
    const COL = 0;

    private $debug = false;
    private $db;
    private $table;
    private $selectOpt = [
        'field' => '*',
        'table' => null,
        'where' => null,
        'groupby' => null,
        'having' => null,
        'orderby' => null,
        'limit' => null,
    ];

    static private $instance = null;

    public function __construct($table = null, $debug = false)
    {
        $this->db = mysqli_connect(
                C('DB_HOST'),
                C('DB_USERNAME'),
                C('DB_PASSWORD'),
                C('DB_NAME'),
                C('DB_PORT'),
                C('DB_SOCKET')
            );
        if (!$this->db)
            E('数据库连接失败，请检查连接选项!');

        $this->debug = $debug;
        $this->table = $table;
    }

    static public function getInstance($table = null)
    {
        if (is_null(self::$instance))
            self::$instance = new Model($table);

        return self::$instance;
    }

    public function __destruct()
    {
        $this->db->close();
    }

    public function __set($name, $value)
    {
        $this->$name = $value;
    }

    public function __get($name)
    {
        return $this->$name;
    }

    static public function exists($db, $table, $field = null, $value = null)
    {
        if ($field === null) {
            $sql = "select * from $table limit 1";
        } else if ($value === null) {
            $sql = "select $field from $table limit 1";
        } else {
            $sql = "select $field from $table where $field='$value' limit 1";
        }

       return $db->query($sql) === FALSE ? FALSE : TRUE;
    }

    public function istable($table)
    {
        if ($table === null)
            $table = $this->table;

        return $table;
    }

    public function create($fileds = array(), $table = null)
    {
        if (($table = $this->istable($table)) === null
                || Model::exists($this->db, $table))
            E("必须指定表名或者数据库中表已经存在!");

        $sql = 'CREATE TABLE '.$table;
        $sql .= '('.implode(",", $fileds).');';

        if ($this->debug)
            dump($sql, 'create table:');

        return $this->db->query($sql);
    }

    public function insert($fields = [], $values = null, $table = null)
    {
        if (($table = $this->istable($table)) === null ||
                ($count = count($fields)) == 0)
            E('必须指定表名和添加的字段!');

        $sql = 'INSERT INTO '.$table;

        if (!is_array($values)) {
            $sql .= ' ('.implode(',', array_keys($fields)).') ';
            $sql .= 'VALUES';
            $sql .= " ('".implode("','", $fields)."')";
        } else {
            $sql .= ' ('.implode(',', $fields).') ';
            $sql .= 'VALUES';

            foreach ($values as $val) {
                if (!is_array($val) || $count != count($val))
                    return FALSE;
                $sql .= " ('".implode("','", $val)."'),";
            }
            $sql = rtrim($sql, ",");
        }

        if ($this->debug)
            dump($sql, 'insert '.$this->table.': ');

       if ($this->db->query($sql))
           return $this->db->insert_id;

        return FALSE;
    }

    public function update($fields = array(), $where = "", $table = null)
    {
        if (($table = $this->istable($table)) === null
                || count($fields) == 0)
            E('必须指定表名和更新字段!');

        $sql = 'UPDATE '.$table. ' SET ';
        foreach ($fields as $key => $val) {
            $sql .= $key."='".$val."',";
        }
        $sql = rtrim($sql, ',').' where '.$where;

        if ($this->debug)
            dump($sql, 'update '.$this->table.': ');

       return $this->db->query($sql);
    }

    public function del($where, $table = null)
    {
        if (($table = $this->istable($table)) === null)
            E('必须指定表名!');

        $sql = 'DELETE FROM '.$table.' '.$where;

        if ($this->debug)
            dump($sql, 'update '.$this->table.': ');

       return $this->db->query($sql);
    }

    public function select($opt = null)
    {
        if ($opt === null)
            return $this->query('SELECT * FROM '.$this->table);

        if (!is_array($opt))
            return $this->query($opt);

        $opt = $opt + $this->selectOpt;

        $sql = 'SELECT '.$op['field'].' FROM ';

        if ($opt['table'] == null)
            $opt['table'] = $this->table;

        if (!$opt['table'])
            E('必须指定表名!');

        $sql .= $op['table'];

        if ($opt['where'] != null)
            $sql .= ' WHERE '.$op['where'];

        if ($opt['groupby'] != null)
            $sql .= ' GROUP BY '.$op['groupby'];

        if ($opt['having'] != null)
            $sql .= ' HAVING '.$op['having'];

        if ($opt['orderby'] != null)
            $sql .= ' ORDER BY '.$op['orderby'];

        if ($opt['limit'] != null)
            $sql .= ' limit '.$op['limit'];

        return $this->query('select * from '.$this->table);
    }

    public function query($sql, $type = Model::ALL)
    {
        $result = $this->db->query($sql);
        if (!$result)
            return FALSE;

        $data = array();
        while ($row = $result->fetch_array(MYSQLI_ASSOC)) {
            if ($type == Model::COL)
                return array_shift($row);
            else if ($type == Model::ROW)
                return $row;

            $data[] = $row;
        }

        return $data;
    }
}
